package com.zw.pm.module.project.change;


import com.zw.pm.config.socket.WebSocketServer;
import com.zw.pm.gen.entity.*;
import com.zw.pm.gen.mapper.MessageMapper;
import com.zw.pm.gen.mapper.ProjectMapper;
import com.zw.pm.gen.mapper.TaskMapper;
import com.zw.pm.gen.mapper.TaskTempMapper;
import com.zw.pm.module.board.single.SingleService;
import com.zw.pm.module.board.single.TaskDao;
import com.zw.pm.module.board.single.TaskModel;
import com.zw.pm.module.config.factory.FactoryDao;
import com.zw.pm.module.config.tasktemp.TaskTempDao;
import com.zw.pm.module.config.tasktemp.TaskTempModel;
import com.zw.pm.module.project.build.ProjectDao;
import com.zw.pm.module.project.build.ProjectModel;
import com.zw.pm.module.system.user.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import static com.zw.pm.constant.Constant.*;

/**
 * @Description: 项目变更 服务层
 *
 * @Author: China.sgl
 * @Date: 2019/9/16 09:11
 */
@SuppressWarnings("all")
@Service
public class ChangeService {

    @Autowired
    private ProjectMapper projectMapper;
    @Autowired
    private ProjectDao projectDao;
    @Autowired
    private FactoryDao factoryDao;
    @Autowired
    private TaskMapper taskMapper;
    @Autowired
    private TaskDao taskDao;
    @Autowired
    private UserDao userDao;
    @Autowired
    private MessageMapper messageMapper;
    @Autowired
    private SingleService singleService;
    @Autowired
    private TaskTempMapper taskTempMapper;
    @Autowired
    private TaskTempDao taskTempDao;

    @Value("${user.upload.path}")
    private String uploadPath;

    public List<TaskTempModel> findTaskTemps() {
        return taskTempDao.findTaskTempAll(new TaskTemp());
    }

    /**
     * 查询生产厂
     *
     * @return list
     */
    public List<Factory> findFactories() {
        return factoryDao.findIdNotIn(new Integer[]{4});
    }

    /**
     * 根据条件查询项目
     *
     * @param project 条件
     * @return list
     */
    public List<ProjectModel> findProject(ProjectModel project) {
        return projectDao.findAlreadyProject(project);
    }

    /**
     * 根据ID查询
     *
     * @param id id
     * @return Project
     */
    public ProjectModel getById(Integer id) {
        ProjectModel projectModel = projectDao.getById(id);
        List<TaskModel> tasks = taskDao.findFactoryTaskByProjectId(id);
        for (TaskModel task : tasks) {
            projectModel.getFactoryIds().add(task.getFactoryId());
        }
        projectModel.getTempTaskIds().addAll(taskDao.findTempTaskIdByProjectId(id));
        return projectModel;
    }

    /**
     * 变更项目
     * 修改项目表 生产厂拼接字符串
     *
     * @param project project
     * @param factoryIds factoryIds
     * @return 行数
     */
    @Transactional
    public int change(Project project, Integer[] factoryIds, Integer[] taskIds) {

        // 生成变更后生产厂名称字符串
        List<Factory> factories = factoryDao.findIdIn(factoryIds);
        StringBuilder sb = new StringBuilder();
        for (Factory factory : factories) {
            sb.append(factory.getName()).append(",");
        }
        String factoriesStr = sb.toString().substring(0, sb.toString().lastIndexOf(","));

        Project p = projectMapper.selectByPrimaryKey(project.getId());

        List<Integer> oldTempIds = taskDao.findTempTaskIdByProjectId(p.getId());
        List<Integer> newTempIds = Arrays.asList(taskIds);

        List<Integer> delTempIds = new ArrayList<>(oldTempIds);
        List<Integer> addTempIds = new ArrayList<>(newTempIds);
        delTempIds.removeAll(addTempIds);
        addTempIds.removeAll(oldTempIds);

        delTempTask(p, delTempIds);
        addTempTask(p, addTempIds);

        // 变更包装任务主体等状态
        TaskModel packTask = taskDao.findTaskByProjectIdAndTaskTempId(p.getId(), 6);
        if (packTask != null) {
            if (project.getHalfSupport() != 0 && packTask.getSupportStatus() == 0) {
                packTask.setSupportStatus(1);
            }
            if (project.getHalfSupport() == 0) {
                packTask.setSupportStatus(0);
            }
            if (project.getIron() != 0 && packTask.getIronStatus() == 0) {
                packTask.setIronStatus(1);
            }
            if (project.getIron() == 0) {
                packTask.setIronStatus(0);
            }
            if (project.getBackType() != 0 && packTask.getBackStatus() == 0) {
                packTask.setBackStatus(1);
            }
            if (project.getBackType() == 0) {
                packTask.setBackStatus(0);
            }
            if (!Arrays.asList(factoryIds).contains(1)
                    && !Arrays.asList(factoryIds).contains(2)
                    && !Arrays.asList(factoryIds).contains(3)) {
                packTask.setMainStatus(0);
            } else {
                packTask.setMainStatus(1);
            }
            taskDao.updateMainStatusByID(packTask);
        }

        // 如果是非体系楼项目， 需要变更生产任务的数量与重量
        if (p.getOrderType() > 1) {
            if (project.getNum() != null && !project.getNum().equals(p.getNum())) {
                taskDao.updateProduceTaskNumByProject(project);
            }
            if (project.getWeight() != null && !project.getWeight().equals(p.getWeight())) {
                taskDao.updateProduceTaskWeightByProject(project);
            }
        }

        // 如果是体系楼项目， 日报表的重量需要从新计算
        if (p.getOrderType() == 1 && project.getUnitWeight() != null && !project.getUnitWeight().equals(p.getUnitWeight())) {
            taskDao.updateTaskDailyWeightByProject(project);
        }

        if (!factoriesStr.equals(p.getFactories())) {
            // 原生产厂ids
            List<Integer> oldFactories = getById(project.getId()).getFactoryIds();
            // 新生产厂ids
            List<Integer> newFactories = Arrays.asList(factoryIds);

            // 如果新生产厂不包含生产一厂，二厂，三厂，删除工艺铝模板
            if (!newFactories.contains(1) && !newFactories.contains(2) && !newFactories.contains(3)) {
                taskDao.deleteTaskByProjectIdAndTaskTempId(project.getId(), 2);
            }
            // 如果原生产厂不包含一二三厂， 新生产厂包含任意（一二三）厂，体系楼类型生成工艺铝模板
            if (p.getOrderType() == 1
                    && !oldFactories.contains(1)
                    && !oldFactories.contains(2)
                    && !oldFactories.contains(3)
                    && (newFactories.contains(1) || newFactories.contains(2) || newFactories.contains(3))) {
                TaskTemp taskTemp = taskTempMapper.selectByPrimaryKey(2);
                Task task = new Task();
                task.setAlias(taskTemp.getName());
                task.setProjectId(project.getId());
                task.setTaskTempId(taskTemp.getId());
                task.setOrderNo(taskTemp.getOrderNo());
                task.setStatus(TASK_STATUS_NOT_BEGIN);
                taskMapper.insert(task);
            }

            // 求需要删除项和新增项
            List<Integer> delFactories = new ArrayList<>(oldFactories);
            List<Integer> addFactories = new ArrayList<>(newFactories);
            delFactories.removeAll(addFactories);
            addFactories.removeAll(oldFactories);

            delTaskAndDaily(project, delFactories);
            addNewTask(p, addFactories);

            singleService.handleProjectStatus(project.getId());
        }

        // 修改项目
        project.setFactories(factoriesStr);
        sendChangeMessage(project);
        return projectDao.updateById(project);
    }

    /** 处理添加新的模板任务 */
    private void addTempTask(Project p, List<Integer> addTempIds) {
        if (addTempIds == null || addTempIds.size() == 0) {
            return ;
        }
        for (Integer addTempId : addTempIds) {
            TaskTemp temp = taskTempDao.findById(addTempId);
            Task task = new Task();
            task.setAlias(temp.getName());
            task.setProjectId(p.getId());
            task.setTaskTempId(temp.getId());
            task.setFactoryId(temp.getFactoryId());
            task.setOrderNo(temp.getOrderNo());
            task.setStatus(TASK_STATUS_NOT_BEGIN);
            taskMapper.insert(task);
        }
    }

    /** 处理删除的模板任务 */
    private void delTempTask(Project p, List<Integer> delTempIds) {
        if (delTempIds == null || delTempIds.size() == 0) {
            return ;
        }
        for (Integer tempId : delTempIds) {
            taskDao.deleteTaskByProjectIdAndTaskTempId(p.getId(), tempId);
        }
    }

    /** 发送项目变更消息 */
    private void sendChangeMessage(Project project) {
        Date currDate = new Date();
        List<User> users = userDao.findByReceiver();
        for (User user : users) {
            Message message = new Message();
            message.setProjectId(project.getId());
            message.setContent(project.getName() + "-- 项目变更");
            message.setCreateTime(currDate);
            message.setStatus(STATUS_NORMAL);
            message.setType(MESSAGE_TYPE_CHANGE);
            message.setSendUserId(1);
            message.setReceiverUserId(user.getId());
            messageMapper.insert(message);
        }
        WebSocketServer.sendInfo("CHANGE");
    }

    /**
     * 处理需要新增的任务
     * 如果包含五厂， 同时新增“工艺铝背楞任务”
     * 添加任务后，将工艺编辑的数量带入生产厂任务中， 此数据不让生产厂修改
     *
     * @param project project
     * @param addFactories 新增生产厂ids
     */
    private void addNewTask(Project project, List<Integer> addFactories) {
        if (addFactories == null || addFactories.size() == 0) {
            return;
        }

        // 体系楼类型项目如果包含模板五厂，创建工艺铝背楞任务
        if (addFactories.contains(FACTORY_FIVE_ID) && project.getOrderType() == 1) {
            TaskTemp taskTemp = taskTempMapper.selectByPrimaryKey(3);
            Task task = new Task();
            task.setAlias(taskTemp.getName());
            task.setProjectId(project.getId());
            task.setTaskTempId(taskTemp.getId());
            task.setFactoryId(taskTemp.getFactoryId());
            task.setOrderNo(taskTemp.getOrderNo());
            task.setStatus(TASK_STATUS_NOT_BEGIN);
            taskMapper.insert(task);
        }

        Integer[] factoryIds = new Integer[addFactories.size()];
        addFactories.toArray(factoryIds);
        List<Factory> factories = factoryDao.findIdIn(factoryIds);
        for (Factory factory : factories) {
            Task task = new Task();
            task.setAlias(factory.getName());
            task.setProjectId(project.getId());
            task.setOrderNo(factory.getOrderNo());
            task.setStatus(STATUS_NORMAL);
            task.setFactoryId(factory.getId());
            taskMapper.insert(task);
        }
        if (project.getOrderType() == 1) {
            // 体系楼类型项目将工艺编辑数量带入生产任务
            Task process1 = taskDao.findTaskByProjectIdAndTempId(project.getId(), THEFIRST_PROCESS_TASK_TEMP_ID);
            taskDao.updateOtherProduceTaskNumByProject(process1);
            taskDao.updateOtherProduceTaskWeightByProject(process1);
            Task process2 = taskDao.findTaskByProjectIdAndTempId(project.getId(), THESECOND_PROCESS_TASK_TEMP_ID);
            taskDao.updateFiveProduceTaskNumByProject(process2);
            taskDao.updateFiveProduceTaskWeightByProject(process2);
        }
        if (project.getOrderType() > 1) {
            // 非休系楼项目将项目数量和重量更新到生产任务
            taskDao.updateProduceTaskNumByProject(project);
            taskDao.updateProduceTaskWeightByProject(project);
        }

    }

    /**
     * 处理需要删除的生产厂任务及日报数据，此操作为真删除，数据无法恢复
     * 如果包含生产五厂， 删除“工艺铝背楞”任务，
     * 删除相关任务的日报表数据
     *
     * @param project project
     * @param delFactories 删除生产厂ids
     */
    private void delTaskAndDaily(Project project, List<Integer> delFactories) {
        for (Integer factoryId : delFactories) {
            if (factoryId == FACTORY_FIVE_ID) {
                taskDao.deleteTaskByProjectIdAndTaskTempId(project.getId(), 3);
            }
            Integer taskId = taskDao.findTaskIdByProjectIdAndFactoryId(project.getId(), factoryId);
            if (taskId != null) {
                taskMapper.deleteByPrimaryKey(taskId);
                taskDao.deleteDailyByTaskId(taskId);
            }
        }
    }

}
